/*
- 线程版服务器（端口8080）：主线程监听TCP，每接受一个连接就创建一个线程处理
- 协议：客户端发送一个double x，服务器计算F(x)=x^2+2*x+1，返回一个double result
- 性能统计：记录线程创建耗时，以及每次请求的服务耗时service_us
- 资源管理：每个连接一次请求即关闭，线程使用pthread_detach释放
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <sys/time.h>

// 计算函数：F(x) = x^2 + 2x + 1
double F(double x) {
    return x * x + 2 * x + 1;
}

void* handle_client(void* arg) {
    // 线程参数是动态分配的socket描述符，需要释放
    int client_sock = *(int*)arg;
    free(arg);
    double x;
    struct timeval s2, e2;
    // 记录服务开始/结束时间并计算服务耗时
    gettimeofday(&s2, NULL);
    read(client_sock, &x, sizeof(double));
    double result = F(x);
    write(client_sock, &result, sizeof(double));
    gettimeofday(&e2, NULL);
    long long service_us = (e2.tv_sec - s2.tv_sec) * 1000000LL + (e2.tv_usec - s2.tv_usec);
    fprintf(stdout, "[thread %lu] service_us=%lld\n", pthread_self(), service_us);
    // 连接完成后关闭socket
    close(client_sock);
    return NULL;
}

int main() {
    // 创建监听socket
    int server_sock = socket(AF_INET, SOCK_STREAM, 0);
    struct sockaddr_in server_addr = {0};
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(8080);
    server_addr.sin_addr.s_addr = INADDR_ANY;
    // 绑定并开始监听
    bind(server_sock, (struct sockaddr*)&server_addr, sizeof(server_addr));
    listen(server_sock, 5);
    printf("Thread Server running...\n");

    struct timeval start, end;
    long long total_us_thread_create = 0;
    unsigned long long requests = 0;

    while (1) {
        // 接受连接，并将socket指针传递给工作线程
        int* client_sock = malloc(sizeof(int));
        *client_sock = accept(server_sock, NULL, NULL);
        pthread_t tid;
        // 记录线程创建耗时
        gettimeofday(&start, NULL);
        pthread_create(&tid, NULL, handle_client, client_sock);
        gettimeofday(&end, NULL);
        long long create_us = (end.tv_sec - start.tv_sec) * 1000000LL + (end.tv_usec - start.tv_usec);
        total_us_thread_create += create_us;
        requests++;
        if (requests % 100 == 0) {
            double avg_create_us = (requests ? (double)total_us_thread_create / (double)requests : 0.0);
            printf("[main] requests=%llu avg_thread_create_us=%.2f\n", requests, avg_create_us);
        }
        // 将线程置为分离状态，自动回收资源
        pthread_detach(tid);
    }
}
